// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// 包asn1实现对DER编码的ASN.1数据结构的解析，
// 如ITU-T Rec X.690所定义。
// None
// 另请参见“ASN.1、BER和DER子集的外行指南”
// http:
package asn1

// ASN.1是用于指定抽象对象和BER、DER、PER、XER等的语法
// 这些对象有不同的编码格式。在这里，我们将进行交易
// 使用DER，可区分的编码规则。DER在X.509中使用，因为
// 它的解析速度很快，而且与BER不同，它对每个对象都有唯一的编码。
// 在计算对象上的散列时，重要的是
// 字节在两端是相同的，DER消除了这个误差范围。
// None
// ASN.1非常复杂，此包不尝试实现
// 无论如何，一切都好。

import (
	"errors"
	"fmt"
	"math"
	"math/big"
	"reflect"
	"strconv"
	"time"
	"unicode/utf16"
	"unicode/utf8"
)

// 结构错误表明ASN.1数据有效，但Go类型无效
// 接收到的数据不匹配。
type StructuralError struct {
	Msg string
}

func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }

// 语法错误表明ASN.1数据无效。
type SyntaxError struct {
	Msg string
}

func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }

// 我们首先依次处理每个基本类型。

// 布尔值

func parseBool(bytes []byte) (ret bool, err error) {
	if len(bytes) != 1 {
		err = SyntaxError{"invalid boolean"}
		return
	}

	// DER要求“如果编码表示布尔值TRUE，
	// 其单个内容八位字节应将所有八位设置为一。”
	// 因此，只有0和255是有效的编码值。
	switch bytes[0] {
	case 0:
		ret = false
	case 0xff:
		ret = true
	default:
		err = SyntaxError{"invalid boolean"}
	}

	return
}

// 整数

// 如果给定字节是有效的DER编码，则checkInteger返回nil
// 整数，否则为错误。
func checkInteger(bytes []byte) error {
	if len(bytes) == 0 {
		return StructuralError{"empty integer"}
	}
	if len(bytes) == 1 {
		return nil
	}
	if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
		return StructuralError{"integer not minimally-encoded"}
	}
	return nil
}

// parseInt64将给定字节视为大端、有符号整数和
// 返回结果。
func parseInt64(bytes []byte) (ret int64, err error) {
	err = checkInteger(bytes)
	if err != nil {
		return
	}
	if len(bytes) > 8 {
		// 在这种情况下，我们将使int64溢出。
		err = StructuralError{"integer too large"}
		return
	}
	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
		ret <<= 8
		ret |= int64(bytes[bytesRead])
	}

	// 上移和下移以签署和扩展结果。
	ret <<= 64 - uint8(len(bytes))*8
	ret >>= 64 - uint8(len(bytes))*8
	return
}

// parseInt将给定字节视为一个大端有符号整数，并返回
// 结果呢。
func parseInt32(bytes []byte) (int32, error) {
	if err := checkInteger(bytes); err != nil {
		return 0, err
	}
	ret64, err := parseInt64(bytes)
	if err != nil {
		return 0, err
	}
	if ret64 != int64(int32(ret64)) {
		return 0, StructuralError{"integer too large"}
	}
	return int32(ret64), nil
}

var bigOne = big.NewInt(1)

// parseBigInt将给定字节视为一个大端有符号整数，并返回
// 结果呢。
func parseBigInt(bytes []byte) (*big.Int, error) {
	if err := checkInteger(bytes); err != nil {
		return nil, err
	}
	ret := new(big.Int)
	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
		// 这是一个负数。
		notBytes := make([]byte, len(bytes))
		for i := range notBytes {
			notBytes[i] = ^bytes[i]
		}
		ret.SetBytes(notBytes)
		ret.Add(ret, bigOne)
		ret.Neg(ret)
		return ret, nil
	}
	ret.SetBytes(bytes)
	return ret, nil
}

// 位串

// BitString是需要ASN.1位字符串类型时使用的结构。A.
// 位字符串被填充到内存中最接近的字节和
// 记录有效位。填充位将为零。
type BitString struct {
	Bytes     []byte // 位压缩成字节。
	BitLength int    // 以位为单位的长度。
}

// At返回给定索引处的位。如果索引超出范围，则将其删除
// 返回false。
func (b BitString) At(i int) int {
	if i < 0 || i >= b.BitLength {
		return 0
	}
	x := i / 8
	y := 7 - uint(i%8)
	return int(b.Bytes[x]>>y) & 1
}

// RightAlign返回填充位位于开头的切片。这个
// 片可以与位字符串共享内存。
func (b BitString) RightAlign() []byte {
	shift := uint(8 - (b.BitLength % 8))
	if shift == 8 || len(b.Bytes) == 0 {
		return b.Bytes
	}

	a := make([]byte, len(b.Bytes))
	a[0] = b.Bytes[0] >> shift
	for i := 1; i < len(b.Bytes); i++ {
		a[i] = b.Bytes[i-1] << (8 - shift)
		a[i] |= b.Bytes[i] >> shift
	}

	return a
}

// parseBitString解析给定字节片中的ASN.1位字符串并返回它。
func parseBitString(bytes []byte) (ret BitString, err error) {
	if len(bytes) == 0 {
		err = SyntaxError{"zero length BIT STRING"}
		return
	}
	paddingBits := int(bytes[0])
	if paddingBits > 7 ||
		len(bytes) == 1 && paddingBits > 0 ||
		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
		err = SyntaxError{"invalid padding bits in BIT STRING"}
		return
	}
	ret.BitLength = (len(bytes)-1)*8 - paddingBits
	ret.Bytes = bytes[1:]
	return
}

// 无效的

// NullRawValue是一个RawValue，其标记设置为ASN.1空类型标记（5）。
var NullRawValue = RawValue{Tag: TagNull}

// NullBytes包含表示DER编码ASN.1 NULL类型的字节。
var NullBytes = []byte{TagNull, 0}

// 对象标识符

// ObjectIdentifier表示ASN.1对象标识符。
type ObjectIdentifier []int

// Equal报告oi和other是否表示相同的标识符。
func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
	if len(oi) != len(other) {
		return false
	}
	for i := 0; i < len(oi); i++ {
		if oi[i] != other[i] {
			return false
		}
	}

	return true
}

func (oi ObjectIdentifier) String() string {
	var s string

	for i, v := range oi {
		if i > 0 {
			s += "."
		}
		s += strconv.Itoa(v)
	}

	return s
}

// parseObjectIdentifier从给定字节和
// 归还它。对象标识符是长度可变的整数序列
// 在层次结构中分配的。
func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) {
	if len(bytes) == 0 {
		err = SyntaxError{"zero length OBJECT IDENTIFIER"}
		return
	}

	// 在最坏的情况下，我们从第一个字节（即
	// 然后每个变量都是一个字节长。
	s = make([]int, len(bytes)+1)

	// 第一个变量是40*value1+value2：
	// 根据此包装，value1只能取值0、1和2。
	// 当value1=0或value1=1时，则value2<=39。当value1=2时，
	// 那么value2就没有限制了。
	v, offset, err := parseBase128Int(bytes, 0)
	if err != nil {
		return
	}
	if v < 80 {
		s[0] = v / 40
		s[1] = v % 40
	} else {
		s[0] = 2
		s[1] = v - 80
	}

	i := 2
	for ; offset < len(bytes); i++ {
		v, offset, err = parseBase128Int(bytes, offset)
		if err != nil {
			return
		}
		s[i] = v
	}
	s = s[0:i]
	return
}

// 列举

// 枚举数组表示为纯整数。
type Enumerated int

// 旗帜

// 标志接受任何数据，如果存在，则设置为true。
type Flag bool

// parseBase128Int从中的给定偏移量解析base-128编码的int
// 给定字节片。它返回值和新的偏移量。
func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
	offset = initOffset
	var ret64 int64
	for shifted := 0; offset < len(bytes); shifted++ {
		// 每字节5*7位==35位数据
		// 因此，对于int32来说，表示不是非最小的，就是太大
		if shifted == 5 {
			err = StructuralError{"base 128 integer too large"}
			return
		}
		ret64 <<= 7
		b := bytes[offset]
		// 整数应该是最小编码的，所以前导的八位字节应该
		// 永远不要是0x80
		if shifted == 0 && b == 0x80 {
			err = SyntaxError{"integer is not minimally encoded"}
			return
		}
		ret64 |= int64(b & 0x7f)
		offset++
		if b&0x80 == 0 {
			ret = int(ret64)
			// 确保返回的值适合所有平台上的int
			if ret64 > math.MaxInt32 {
				err = StructuralError{"base 128 integer too large"}
			}
			return
		}
	}
	err = SyntaxError{"truncated base 128 integer"}
	return
}

// UTCTime

func parseUTCTime(bytes []byte) (ret time.Time, err error) {
	s := string(bytes)

	formatStr := "0601021504Z0700"
	ret, err = time.Parse(formatStr, s)
	if err != nil {
		formatStr = "060102150405Z0700"
		ret, err = time.Parse(formatStr, s)
	}
	if err != nil {
		return
	}

	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
		return
	}

	if ret.Year() >= 2050 {
		// UTCTime仅编码2050年之前的时间。请参阅https:
		ret = ret.AddDate(-100, 0, 0)
	}

	return
}

// ParseGeneratedTime从给定的字节片解析GeneratedTime
// 并返回结果时间。
func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
	const formatStr = "20060102150405Z0700"
	s := string(bytes)

	if ret, err = time.Parse(formatStr, s); err != nil {
		return
	}

	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
	}

	return
}

// 数字串

// parseNumericString从给定字节数组解析ASN.1 NumericString
// 并返回它。
func parseNumericString(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if !isNumeric(b) {
			return "", SyntaxError{"NumericString contains invalid character"}
		}
	}
	return string(bytes), nil
}

// isNumeric报告给定的b是否在ASN.1 NumericString集合中。
func isNumeric(b byte) bool {
	return '0' <= b && b <= '9' ||
		b == ' '
}

// 可打印字符串

// parsePrintableString从给定字节解析ASN.1 PrintableString
// 数组并返回它。
func parsePrintableString(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if !isPrintable(b, allowAsterisk, allowAmpersand) {
			err = SyntaxError{"PrintableString contains invalid character"}
			return
		}
	}
	ret = string(bytes)
	return
}

type asteriskFlag bool
type ampersandFlag bool

const (
	allowAsterisk  asteriskFlag = true
	rejectAsterisk asteriskFlag = false

	allowAmpersand  ampersandFlag = true
	rejectAmpersand ampersandFlag = false
)

// iPrintable报告给定的b是否在ASN.1可打印字符串集中。
// 如果星号为AllowsRisk，则还允许使用“*”，以反映现有的
// 实践如果允许使用符号AND，则也允许使用“&”。
func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool {
	return 'a' <= b && b <= 'z' ||
		'A' <= b && b <= 'Z' ||
		'0' <= b && b <= '9' ||
		'\'' <= b && b <= ')' ||
		'+' <= b && b <= '/' ||
		b == ' ' ||
		b == ':' ||
		b == '=' ||
		b == '?' ||
		// 从技术上讲，这在可打印字符串中是不允许的。
		// 但是，带有通配符字符串的x509证书不会
		// 始终使用正确的字符串类型，以便我们允许它。
		(bool(asterisk) && b == '*') ||
		// 这在技术上也是不允许的。然而，并非如此
		// 这不仅是比较普遍的，而且也有很多原因
		// 包含它的少数CA证书。至少
		// 其中一个要到2027年才会到期。
		(bool(ampersand) && b == '&')
}

// IA5String

// parseIA5String从给定的字符串中解析ASN.1 IA5String（ASCII字符串）
// 字节片并返回它。
func parseIA5String(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if b >= utf8.RuneSelf {
			err = SyntaxError{"IA5String contains invalid character"}
			return
		}
	}
	ret = string(bytes)
	return
}

// T61串

// parseT61String从给定字符串解析ASN.1 T61String（8位干净字符串）
// 字节片并返回它。
func parseT61String(bytes []byte) (ret string, err error) {
	return string(bytes), nil
}

// UTF8字符串

// parseUTF8String从给定字节解析ASN.1 UTF8String（原始UTF-8）
// 数组并返回它。
func parseUTF8String(bytes []byte) (ret string, err error) {
	if !utf8.Valid(bytes) {
		return "", errors.New("asn1: invalid UTF-8 string")
	}
	return string(bytes), nil
}

// BMPString

// parseBMPString解析ASN.1 BMPString（基本多语言平面）
// ISO/IEC/ITU 10646-1），并返回它。
func parseBMPString(bmpString []byte) (string, error) {
	if len(bmpString)%2 != 0 {
		return "", errors.New("pkcs12: odd-length BMP string")
	}

	// 如果存在，则去除终端。
	if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
		bmpString = bmpString[:l-2]
	}

	s := make([]uint16, 0, len(bmpString)/2)
	for len(bmpString) > 0 {
		s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
		bmpString = bmpString[2:]
	}

	return string(utf16.Decode(s)), nil
}

// RawValue表示未编码的ASN.1对象。
type RawValue struct {
	Class, Tag int
	IsCompound bool
	Bytes      []byte
	FullBytes  []byte // 包括标记和长度
}

// RawContent用于表示需要删除未编码的DER数据
// 为结构保留。要使用它，结构的第一个字段必须具有
// 这种。任何其他字段具有此类型都是错误的。
type RawContent []byte

// 标记

// parseTagAndLength从给定偏移量解析ASN.1标记和长度对
// 转换为字节片。它返回解析后的数据和新的偏移量。设置和
// 集合（标签17）被映射到序列和序列（标签16），因为我们
// 在此代码中，不要区分有序对象和无序对象。
func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
	offset = initOffset
	// 如果没有至少一个参数，则不应调用parseTagAndLength
	// 要读取的字节。因此，该检查是针对稳健性：
	if offset >= len(bytes) {
		err = errors.New("asn1: internal error in parseTagAndLength")
		return
	}
	b := bytes[offset]
	offset++
	ret.class = int(b >> 6)
	ret.isCompound = b&0x20 == 0x20
	ret.tag = int(b & 0x1f)

	// 如果设置了底部五位，则标签号实际上是以128为基数
	// 事后编码
	if ret.tag == 0x1f {
		ret.tag, offset, err = parseBase128Int(bytes, offset)
		if err != nil {
			return
		}
		// 标签应该以最小的形式编码。
		if ret.tag < 0x1f {
			err = SyntaxError{"non-minimal tag"}
			return
		}
	}
	if offset >= len(bytes) {
		err = SyntaxError{"truncated tag or length"}
		return
	}
	b = bytes[offset]
	offset++
	if b&0x80 == 0 {
		// 长度以底部7位编码。
		ret.length = int(b & 0x7f)
	} else {
		// 底部7位给出要跟随的长度字节数。
		numBytes := int(b & 0x7f)
		if numBytes == 0 {
			err = SyntaxError{"indefinite length found (not DER)"}
			return
		}
		ret.length = 0
		for i := 0; i < numBytes; i++ {
			if offset >= len(bytes) {
				err = SyntaxError{"truncated tag or length"}
				return
			}
			b = bytes[offset]
			offset++
			if ret.length >= 1<<23 {
				// 我们不能在没有时间的情况下把ret.length向上移动
				// 满溢的。
				err = StructuralError{"length too large"}
				return
			}
			ret.length <<= 8
			ret.length |= int(b)
			if ret.length == 0 {
				// DER要求长度最小。
				err = StructuralError{"superfluous leading zeros in length"}
				return
			}
		}
		// 短长度必须以短形式编码。
		if ret.length < 0x80 {
			err = StructuralError{"non-minimal length"}
			return
		}
	}

	return
}

// parseSequenceOf用于值序列和值集。它试图解析
// 来自给定字节片的许多ASN.1值，并以
// 给定类型的Go值的切片。
func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) {
	matchAny, expectedTag, compoundType, ok := getUniversalType(elemType)
	if !ok {
		err = StructuralError{"unknown Go type for slice"}
		return
	}

	// 首先我们迭代输入并计算元素的数量，
	// 检查每种情况下的类型是否正确。
	numElements := 0
	for offset := 0; offset < len(bytes); {
		var t tagAndLength
		t, offset, err = parseTagAndLength(bytes, offset)
		if err != nil {
			return
		}
		switch t.tag {
		case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
			// 我们假设其他各种字符串类型是
			// 可打印字符串，以便可以打印一系列字符串
			// 解析为[]字符串。
			t.tag = TagPrintableString
		case TagGeneralizedTime, TagUTCTime:
			// 同样，这两种时间类型被视为相同的。
			t.tag = TagUTCTime
		}

		if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) {
			err = StructuralError{"sequence tag mismatch"}
			return
		}
		if invalidLength(offset, t.length, len(bytes)) {
			err = SyntaxError{"truncated sequence"}
			return
		}
		offset += t.length
		numElements++
	}
	ret = reflect.MakeSlice(sliceType, numElements, numElements)
	params := fieldParameters{}
	offset := 0
	for i := 0; i < numElements; i++ {
		offset, err = parseField(ret.Index(i), bytes, offset, params)
		if err != nil {
			return
		}
	}
	return
}

var (
	bitStringType        = reflect.TypeOf(BitString{})
	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
	enumeratedType       = reflect.TypeOf(Enumerated(0))
	flagType             = reflect.TypeOf(Flag(false))
	timeType             = reflect.TypeOf(time.Time{})
	rawValueType         = reflect.TypeOf(RawValue{})
	rawContentsType      = reflect.TypeOf(RawContent(nil))
	bigIntType           = reflect.TypeOf(new(big.Int))
)

// invalidLength报告偏移+长度>切片长度，或者
// 添加会溢出。
func invalidLength(offset, length, sliceLength int) bool {
	return offset+length < offset || offset+length > sliceLength
}

// parseField是主要的解析函数。给定一个字节片和一个偏移量
// 在数组中，它将尝试解析一个合适的ASN.1值并存储它
// 在给定的值中。
func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) {
	offset = initOffset
	fieldType := v.Type()

	// 如果我们已经用完了数据，可能是因为最后有可选的元素。
	if offset == len(bytes) {
		if !setDefaultValue(v, params) {
			err = SyntaxError{"sequence truncated"}
		}
		return
	}

	// 处理任何类型的问题。
	if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
		var t tagAndLength
		t, offset, err = parseTagAndLength(bytes, offset)
		if err != nil {
			return
		}
		if invalidLength(offset, t.length, len(bytes)) {
			err = SyntaxError{"data truncated"}
			return
		}
		var result interface{}
		if !t.isCompound && t.class == ClassUniversal {
			innerBytes := bytes[offset : offset+t.length]
			switch t.tag {
			case TagPrintableString:
				result, err = parsePrintableString(innerBytes)
			case TagNumericString:
				result, err = parseNumericString(innerBytes)
			case TagIA5String:
				result, err = parseIA5String(innerBytes)
			case TagT61String:
				result, err = parseT61String(innerBytes)
			case TagUTF8String:
				result, err = parseUTF8String(innerBytes)
			case TagInteger:
				result, err = parseInt64(innerBytes)
			case TagBitString:
				result, err = parseBitString(innerBytes)
			case TagOID:
				result, err = parseObjectIdentifier(innerBytes)
			case TagUTCTime:
				result, err = parseUTCTime(innerBytes)
			case TagGeneralizedTime:
				result, err = parseGeneralizedTime(innerBytes)
			case TagOctetString:
				result = innerBytes
			case TagBMPString:
				result, err = parseBMPString(innerBytes)
			default:
				// 如果我们不知道如何处理该类型，我们只将值保留为nil。
			}
		}
		offset += t.length
		if err != nil {
			return
		}
		if result != nil {
			v.Set(reflect.ValueOf(result))
		}
		return
	}

	t, offset, err := parseTagAndLength(bytes, offset)
	if err != nil {
		return
	}
	if params.explicit {
		expectedClass := ClassContextSpecific
		if params.application {
			expectedClass = ClassApplication
		}
		if offset == len(bytes) {
			err = StructuralError{"explicit tag has no child"}
			return
		}
		if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
			if fieldType == rawValueType {
				// 不应为rawValue分析内部元素。
			} else if t.length > 0 {
				t, offset, err = parseTagAndLength(bytes, offset)
				if err != nil {
					return
				}
			} else {
				if fieldType != flagType {
					err = StructuralError{"zero length explicit tag was not an asn1.Flag"}
					return
				}
				v.SetBool(true)
				return
			}
		} else {
			// 标记不匹配，可能是可选元素。
			ok := setDefaultValue(v, params)
			if ok {
				offset = initOffset
			} else {
				err = StructuralError{"explicitly tagged member didn't match"}
			}
			return
		}
	}

	matchAny, universalTag, compoundType, ok1 := getUniversalType(fieldType)
	if !ok1 {
		err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
		return
	}

	// 字符串的特殊情况：所有ASN.1字符串类型都映射到Go
	// 键入字符串。getUniversalType返回PrintableString的标记
	// 当它看到一个字符串时，如果我们在
	// 电线，我们更改通用类型以匹配。
	if universalTag == TagPrintableString {
		if t.class == ClassUniversal {
			switch t.tag {
			case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
				universalTag = t.tag
			}
		} else if params.stringType != 0 {
			universalTag = params.stringType
		}
	}

	// 时间的特例：UTCTime和GeneralizedTime都映射到
	// 输入时间。
	if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
		universalTag = TagGeneralizedTime
	}

	if params.set {
		universalTag = TagSet
	}

	matchAnyClassAndTag := matchAny
	expectedClass := ClassUniversal
	expectedTag := universalTag

	if !params.explicit && params.tag != nil {
		expectedClass = ClassContextSpecific
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	if !params.explicit && params.application && params.tag != nil {
		expectedClass = ClassApplication
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	if !params.explicit && params.private && params.tag != nil {
		expectedClass = ClassPrivate
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	// 我们现在已经打开了任何显式标记。
	if !matchAnyClassAndTag && (t.class != expectedClass || t.tag != expectedTag) ||
		(!matchAny && t.isCompound != compoundType) {
		// 标签不匹配。同样，它可以是可选元素。
		ok := setDefaultValue(v, params)
		if ok {
			offset = initOffset
		} else {
			err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
		}
		return
	}
	if invalidLength(offset, t.length, len(bytes)) {
		err = SyntaxError{"data truncated"}
		return
	}
	innerBytes := bytes[offset : offset+t.length]
	offset += t.length

	// 我们首先处理这个包中定义的结构。
	switch v := v.Addr().Interface().(type) {
	case *RawValue:
		*v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
		return
	case *ObjectIdentifier:
		*v, err = parseObjectIdentifier(innerBytes)
		return
	case *BitString:
		*v, err = parseBitString(innerBytes)
		return
	case *time.Time:
		if universalTag == TagUTCTime {
			*v, err = parseUTCTime(innerBytes)
			return
		}
		*v, err = parseGeneralizedTime(innerBytes)
		return
	case *Enumerated:
		parsedInt, err1 := parseInt32(innerBytes)
		if err1 == nil {
			*v = Enumerated(parsedInt)
		}
		err = err1
		return
	case *Flag:
		*v = true
		return
	case **big.Int:
		parsedInt, err1 := parseBigInt(innerBytes)
		if err1 == nil {
			*v = parsedInt
		}
		err = err1
		return
	}
	switch val := v; val.Kind() {
	case reflect.Bool:
		parsedBool, err1 := parseBool(innerBytes)
		if err1 == nil {
			val.SetBool(parsedBool)
		}
		err = err1
		return
	case reflect.Int, reflect.Int32, reflect.Int64:
		if val.Type().Size() == 4 {
			parsedInt, err1 := parseInt32(innerBytes)
			if err1 == nil {
				val.SetInt(int64(parsedInt))
			}
			err = err1
		} else {
			parsedInt, err1 := parseInt64(innerBytes)
			if err1 == nil {
				val.SetInt(parsedInt)
			}
			err = err1
		}
		return
	// TODO（dfc）添加对其余整数类型的支持
	case reflect.Struct:
		structType := fieldType

		for i := 0; i < structType.NumField(); i++ {
			if !structType.Field(i).IsExported() {
				err = StructuralError{"struct contains unexported fields"}
				return
			}
		}

		if structType.NumField() > 0 &&
			structType.Field(0).Type == rawContentsType {
			bytes := bytes[initOffset:offset]
			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
		}

		innerOffset := 0
		for i := 0; i < structType.NumField(); i++ {
			field := structType.Field(i)
			if i == 0 && field.Type == rawContentsType {
				continue
			}
			innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
			if err != nil {
				return
			}
		}
		// 我们在序列的末尾允许额外的字节，因为
		// 在X.509中，将元素添加到末尾已被用作
		// 版本号增加了。
		return
	case reflect.Slice:
		sliceType := fieldType
		if sliceType.Elem().Kind() == reflect.Uint8 {
			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
			reflect.Copy(val, reflect.ValueOf(innerBytes))
			return
		}
		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
		if err1 == nil {
			val.Set(newSlice)
		}
		err = err1
		return
	case reflect.String:
		var v string
		switch universalTag {
		case TagPrintableString:
			v, err = parsePrintableString(innerBytes)
		case TagNumericString:
			v, err = parseNumericString(innerBytes)
		case TagIA5String:
			v, err = parseIA5String(innerBytes)
		case TagT61String:
			v, err = parseT61String(innerBytes)
		case TagUTF8String:
			v, err = parseUTF8String(innerBytes)
		case TagGeneralString:
			// ISO-2022/ECMA-35中规定了通用管柱，
			// 简要回顾表明，它包括结构
			// 允许编码更改中间字符串和
			// 这样的我们放弃并将其作为8位字符串传递。
			v, err = parseT61String(innerBytes)
		case TagBMPString:
			v, err = parseBMPString(innerBytes)

		default:
			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
		}
		if err == nil {
			val.SetString(v)
		}
		return
	}
	err = StructuralError{"unsupported: " + v.Type().String()}
	return
}

// canHaveDefaultValue报告k是否是我们将设置为默认值的类型
// 价值为。（本质上是一个有符号整数。）
func canHaveDefaultValue(k reflect.Kind) bool {
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return true
	}

	return false
}

// setDefaultValue用于将标记字符串中的默认值安装到
// 价值。如果该字段是可选的，即使是默认值，也是成功的
// 未提供或无法将其安装到值中。
func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
	if !params.optional {
		return
	}
	ok = true
	if params.defaultValue == nil {
		return
	}
	if canHaveDefaultValue(v.Kind()) {
		v.SetInt(*params.defaultValue)
	}
	return
}

// 解组器解析DER编码的ASN.1数据结构b
// 并使用reflect包填充val指向的任意值。
// 因为解组器使用反射包，所以结构
// 写入的字段名必须使用大写字段名。如果val
// 如果为nil或不是指针，则解组将返回一个错误。
// None
// 解析b后，剩余的、未用于填充的任何字节
// 瓦尔将在休息时返回。将序列解析为结构时，
// 序列中没有匹配项的任何尾随元素
// val中的字段将不包括在rest中，因为这些字段被考虑在内
// 序列的有效元素，而不是尾随数据。
// None
// ASN.1整数可以写入int、int32、int64、，
// 或*big.Int（来自数学/大软件包）。
// 如果编码值不适合Go类型，
// 解组返回一个分析错误。
// None
// ASN.1位字符串可以写入位字符串。
// None
// ASN.1八位字节字符串可以写入[]字节。
// None
// ASN.1对象标识符可以写入
// 目标识别器。
// None
// 枚举的ASN.1可以写入枚举的ASN.1。
// None
// ASN.1 UTCTIME或GENERALIZEDTIME可以写入time.time。
// None
// ASN.1可打印字符串、IA5String或NumericString可以写入字符串。
// None
// 上述任何ASN.1值都可以写入接口{}。
// 存储在接口中的值具有相应的Go类型。
// 对于整数，该类型为int64。
// None
// 可以写入ASN.1 x序列或x集
// 如果x可以写入切片的元素类型，则将其写入切片。
// None
// ASN.1序列或集合可以写入结构
// 如果序列中的每个元素都可以
// 写入结构中的相应元素。
// None
// 结构字段上的以下标记对解组具有特殊意义：
// None
// 应用程序指定使用应用程序标记
// private指定使用私有标记
// 默认值：x设置可选整数字段的默认值（仅当可选字段也存在时使用）
// explicit指定附加的显式标记包装隐式标记
// 可选将该字段标记为ASN.1可选
// set导致预期的是set，而不是序列类型
// 标签：x指定ASN.1标签号；暗示ASN.1特定于上下文
// None
// 将带有隐式标记的ASN.1值解码为字符串字段时，
// 解组将默认为可打印字符串，该字符串不支持
// 字符，如“@”和“&”。要强制使用其他编码，请使用以下命令
// 标签：
// None
// ia5导致字符串作为ASN.1 IA5String值被解组
// numeric导致字符串作为ASN.1 NumericString值取消编组
// utf8导致字符串被解组为ASN.1 UTF8String值
// None
// 如果结构的第一个字段的类型为RawContent，则为raw
// 结构的ASN1内容将存储在其中。
// None
// 如果切片类型的名称以“SET”结尾，则将其视为
// “设置”标签已设置在其上。这将导致将类型解释为
// x的集合而不是x的序列。这可用于嵌套切片
// 其中无法提供结构标记。
// None
// 不支持其他ASN.1类型；如果遇到他们,，
// 解组返回一个分析错误。
func Unmarshal(b []byte, val interface{}) (rest []byte, err error) {
	return UnmarshalWithParams(b, val, "")
}

// invalidUnmarshalError描述传递给Unmarshal的无效参数。
// （Unmarshal的参数必须是非nil指针。）
type invalidUnmarshalError struct {
	Type reflect.Type
}

func (e *invalidUnmarshalError) Error() string {
	if e.Type == nil {
		return "asn1: Unmarshal recipient value is nil"
	}

	if e.Type.Kind() != reflect.Ptr {
		return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String()
	}
	return "asn1: Unmarshal recipient value is nil " + e.Type.String()
}

// UnmarshalWithParams允许为
// 顶级元素。参数的形式与字段标记相同。
func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) {
	v := reflect.ValueOf(val)
	if v.Kind() != reflect.Ptr || v.IsNil() {
		return nil, &invalidUnmarshalError{reflect.TypeOf(val)}
	}
	offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params))
	if err != nil {
		return nil, err
	}
	return b[offset:], nil
}
